﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Priority_Queue
{
	// Token: 0x02000327 RID: 807
	public sealed class GenericPriorityQueue<TItem, TPriority> : IFixedSizePriorityQueue<TItem, TPriority>, IPriorityQueue<TItem, TPriority>, IEnumerable<TItem>, IEnumerable where TItem : GenericPriorityQueueNode<TPriority> where TPriority : IComparable<TPriority>
	{
		// Token: 0x060014C8 RID: 5320 RVA: 0x0008859B File Offset: 0x0008679B
		public GenericPriorityQueue(int maxNodes)
		{
			this._numNodes = 0;
			this._nodes = new TItem[maxNodes + 1];
			this._numNodesEverEnqueued = 0L;
		}

		// Token: 0x17000348 RID: 840
		// (get) Token: 0x060014C9 RID: 5321 RVA: 0x000885C0 File Offset: 0x000867C0
		public int Count
		{
			get
			{
				return this._numNodes;
			}
		}

		// Token: 0x17000349 RID: 841
		// (get) Token: 0x060014CA RID: 5322 RVA: 0x000885C8 File Offset: 0x000867C8
		public int MaxSize
		{
			get
			{
				return this._nodes.Length - 1;
			}
		}

		// Token: 0x060014CB RID: 5323 RVA: 0x000885D4 File Offset: 0x000867D4
		public void Clear()
		{
			Array.Clear(this._nodes, 1, this._numNodes);
			this._numNodes = 0;
		}

		// Token: 0x060014CC RID: 5324 RVA: 0x000885EF File Offset: 0x000867EF
		public bool Contains(TItem node)
		{
			return this._nodes[node.QueueIndex] == node;
		}

		// Token: 0x060014CD RID: 5325 RVA: 0x00088618 File Offset: 0x00086818
		public void Enqueue(TItem node, TPriority priority)
		{
			node.Priority = priority;
			this._numNodes++;
			this._nodes[this._numNodes] = node;
			node.QueueIndex = this._numNodes;
			long numNodesEverEnqueued;
			this._numNodesEverEnqueued = (numNodesEverEnqueued = this._numNodesEverEnqueued) + 1L;
			node.InsertionIndex = numNodesEverEnqueued;
			this.CascadeUp(this._nodes[this._numNodes]);
		}

		// Token: 0x060014CE RID: 5326 RVA: 0x0008869C File Offset: 0x0008689C
		private void Swap(TItem node1, TItem node2)
		{
			this._nodes[node1.QueueIndex] = node2;
			this._nodes[node2.QueueIndex] = node1;
			int queueIndex = node1.QueueIndex;
			node1.QueueIndex = node2.QueueIndex;
			node2.QueueIndex = queueIndex;
		}

		// Token: 0x060014CF RID: 5327 RVA: 0x00088714 File Offset: 0x00086914
		private void CascadeUp(TItem node)
		{
			for (int i = node.QueueIndex / 2; i >= 1; i = node.QueueIndex / 2)
			{
				TItem titem = this._nodes[i];
				if (this.HasHigherPriority(titem, node))
				{
					break;
				}
				this.Swap(node, titem);
			}
		}

		// Token: 0x060014D0 RID: 5328 RVA: 0x00088774 File Offset: 0x00086974
		private void CascadeDown(TItem node)
		{
			int num = node.QueueIndex;
			for (;;)
			{
				TItem titem = node;
				int num2 = 2 * num;
				if (num2 > this._numNodes)
				{
					break;
				}
				TItem titem2 = this._nodes[num2];
				if (this.HasHigherPriority(titem2, titem))
				{
					titem = titem2;
				}
				int num3 = num2 + 1;
				if (num3 <= this._numNodes)
				{
					TItem titem3 = this._nodes[num3];
					if (this.HasHigherPriority(titem3, titem))
					{
						titem = titem3;
					}
				}
				if (titem == node)
				{
					goto IL_D1;
				}
				this._nodes[num] = titem;
				int queueIndex = titem.QueueIndex;
				titem.QueueIndex = num;
				num = queueIndex;
			}
			node.QueueIndex = num;
			this._nodes[num] = node;
			return;
			IL_D1:
			node.QueueIndex = num;
			this._nodes[num] = node;
		}

		// Token: 0x060014D1 RID: 5329 RVA: 0x00088878 File Offset: 0x00086A78
		private bool HasHigherPriority(TItem higher, TItem lower)
		{
			TPriority priority = higher.Priority;
			int num = priority.CompareTo(lower.Priority);
			return num < 0 || (num == 0 && higher.InsertionIndex < lower.InsertionIndex);
		}

		// Token: 0x060014D2 RID: 5330 RVA: 0x000888E0 File Offset: 0x00086AE0
		public TItem Dequeue()
		{
			TItem titem = this._nodes[1];
			this.Remove(titem);
			return titem;
		}

		// Token: 0x060014D3 RID: 5331 RVA: 0x00088904 File Offset: 0x00086B04
		public void Resize(int maxNodes)
		{
			TItem[] array = new TItem[maxNodes + 1];
			int num = Math.Min(maxNodes, this._numNodes);
			for (int i = 1; i <= num; i++)
			{
				array[i] = this._nodes[i];
			}
			this._nodes = array;
		}

		// Token: 0x1700034A RID: 842
		// (get) Token: 0x060014D4 RID: 5332 RVA: 0x00088953 File Offset: 0x00086B53
		public TItem First
		{
			get
			{
				return this._nodes[1];
			}
		}

		// Token: 0x060014D5 RID: 5333 RVA: 0x00088961 File Offset: 0x00086B61
		public void UpdatePriority(TItem node, TPriority priority)
		{
			node.Priority = priority;
			this.OnNodeUpdated(node);
		}

		// Token: 0x060014D6 RID: 5334 RVA: 0x00088978 File Offset: 0x00086B78
		private void OnNodeUpdated(TItem node)
		{
			int num = node.QueueIndex / 2;
			TItem lower = this._nodes[num];
			if (num > 0 && this.HasHigherPriority(node, lower))
			{
				this.CascadeUp(node);
			}
			else
			{
				this.CascadeDown(node);
			}
		}

		// Token: 0x060014D7 RID: 5335 RVA: 0x000889CC File Offset: 0x00086BCC
		public void Remove(TItem node)
		{
			if (node.QueueIndex == this._numNodes)
			{
				this._nodes[this._numNodes] = (TItem)((object)null);
				this._numNodes--;
				return;
			}
			TItem titem = this._nodes[this._numNodes];
			this.Swap(node, titem);
			this._nodes[this._numNodes] = (TItem)((object)null);
			this._numNodes--;
			this.OnNodeUpdated(titem);
		}

		// Token: 0x060014D8 RID: 5336 RVA: 0x00088A60 File Offset: 0x00086C60
		public IEnumerator<TItem> GetEnumerator()
		{
			for (int i = 1; i <= this._numNodes; i++)
			{
				yield return this._nodes[i];
			}
			yield break;
		}

		// Token: 0x060014D9 RID: 5337 RVA: 0x00088A7B File Offset: 0x00086C7B
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		// Token: 0x060014DA RID: 5338 RVA: 0x00088A84 File Offset: 0x00086C84
		public bool IsValidQueue()
		{
			for (int i = 1; i < this._nodes.Length; i++)
			{
				if (this._nodes[i] != null)
				{
					int num = 2 * i;
					if (num < this._nodes.Length && this._nodes[num] != null && this.HasHigherPriority(this._nodes[num], this._nodes[i]))
					{
						return false;
					}
					int num2 = num + 1;
					if (num2 < this._nodes.Length && this._nodes[num2] != null && this.HasHigherPriority(this._nodes[num2], this._nodes[i]))
					{
						return false;
					}
				}
			}
			return true;
		}

		// Token: 0x040017B2 RID: 6066
		private int _numNodes;

		// Token: 0x040017B3 RID: 6067
		private TItem[] _nodes;

		// Token: 0x040017B4 RID: 6068
		private long _numNodesEverEnqueued;
	}
}
